package main

import (
	"context"
	"flag"
	"fmt"
	"github.com/apache/rocketmq-client-go/v2"
	"github.com/apache/rocketmq-client-go/v2/consumer"
	"github.com/apache/rocketmq-client-go/v2/primitive"
	"github.com/google/uuid"
	"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/propagation"
	"go.uber.org/zap"
	"google.golang.org/grpc"
	"google.golang.org/grpc/health"
	"google.golang.org/grpc/health/grpc_health_v1"
	"log"
	"mxshop_srvs/inventory_srv/global"
	"mxshop_srvs/inventory_srv/handler"
	"mxshop_srvs/inventory_srv/initalize"
	"mxshop_srvs/inventory_srv/proto"
	"mxshop_srvs/inventory_srv/utils"
	"mxshop_srvs/inventory_srv/utils/register/consul"
	"net"
	"os"
	"os/signal"
	"syscall"
)

func main() {
	IP := flag.String("ip", "0.0.0.0", "ip地址")
	Port := flag.Int("port", 0, "端口号")
	flag.Parse()

	// 初始化
	initalize.InitLogger()
	initalize.InitConfig()
	initalize.InitDB()

	if *Port == 0 {
		*Port, _ = utils.GetFreePort()
	}

	tp, err := utils.TracerProvider(fmt.Sprintf("http://%s:%d/api/traces", global.ServerConfig.JaegerInfo.Host, global.ServerConfig.JaegerInfo.Port))
	if err != nil {
		zap.S().Debug(err)
	}
	otel.SetTracerProvider(tp)
	otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
	server := grpc.NewServer(
		grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()),
		grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor()),
	)
	proto.RegisterInventoryServer(server, &handler.InventoryServer{
		UnimplementedInventoryServer: proto.UnimplementedInventoryServer{},
	})
	// 注册服务健康检查
	grpc_health_v1.RegisterHealthServer(server, health.NewServer())

	//服务注册
	registerClient := consul.NewRegistryClient(global.ServerConfig.ConsulInfo.Host, global.ServerConfig.ConsulInfo.Port)
	serviceId := fmt.Sprintf("%s", uuid.New())
	err = registerClient.Register(global.ServerConfig.Host, *Port, global.ServerConfig.Name, global.ServerConfig.Tags, serviceId)
	if err != nil {
		zap.S().Panic("[inventory-srv] 服务注册失败:", err.Error())
	}

	lis, err := net.Listen("tcp", fmt.Sprintf("%s:%d", *IP, *Port))
	if err != nil {
		zap.S().Panic("[inventory-srv] 服务监听端口失败:" + err.Error())
	}

	// 监听库存归还 topic
	c, _ := rocketmq.NewPushConsumer(
		consumer.WithGroupName("mxshop-inventory"),
		consumer.WithNsResolver(primitive.NewPassthroughResolver([]string{fmt.Sprintf("%s:%d", global.ServerConfig.RocketMq.Host, global.ServerConfig.RocketMq.Port)})),
	)
	if err = c.Subscribe("order_reback", consumer.MessageSelector{}, handler.AutoReback); err != nil {
		panic(fmt.Sprintf("读取 消息 失败: %s", err.Error()))
	}
	if err = c.Start(); err != nil {
		panic(fmt.Sprintf("启动 producer 失败: %s", err))
	}

	// 启动服务
	go func() {
		err = server.Serve(lis)
		if err != nil {
			zap.S().Panic("[inventory-srv] 服务启动失败:" + err.Error())
		}
	}()
	zap.S().Debugf("[inventory-srv] 服务启动成功 端口: %d", *Port)

	// 接收终止信号
	quit := make(chan os.Signal)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
	_ = c.Shutdown()
	if err := tp.Shutdown(context.Background()); err != nil {
		log.Printf("关闭跟踪程序提供程序时出错: %v", err)
	}
	if err = registerClient.DeRegister(serviceId); err != nil {
		zap.S().Info("[inventory-srv] consul 服务注销失败:" + err.Error())
	} else {
		zap.S().Info("[inventory-srv] consul 服务注销成功")
	}
}
